package com.shsh.safemanage.action;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.json.JSONObject;

import com.shsh.safemanage.dao.DaoCreator;
import com.shsh.safemanage.dao.DepartmentDao;
import com.shsh.safemanage.dao.PostCheckDao;
import com.shsh.safemanage.dao.ProblemDao;
import com.shsh.safemanage.dao.RoleDao;
import com.shsh.safemanage.dao.UserDao;
import com.shsh.safemanage.model.Department1;
import com.shsh.safemanage.model.Department1PostcheckMapping;
import com.shsh.safemanage.model.PostCheck;
import com.shsh.safemanage.model.PostcheckDailyReportItem;
import com.shsh.safemanage.model.PostcheckDepartMonthCheckSummaryReport;
import com.shsh.safemanage.model.PostcheckDepartMonthCheckSummaryRow;
import com.shsh.safemanage.model.PostcheckMonthCheckSummaryCell;
import com.shsh.safemanage.model.PostcheckMonthCheckSummaryReport;
import com.shsh.safemanage.model.PostcheckMonthQualityReport;
import com.shsh.safemanage.model.PostcheckMonthQualityReport.ChushiReport;
import com.shsh.safemanage.model.PostcheckMonthQualityReport.ShiyebuReport;
import com.shsh.safemanage.model.PostcheckMonthQualityReport.ShiyebuReport.ShiyebuReportCell;
import com.shsh.safemanage.model.PostcheckMonthSanweiReport;
import com.shsh.safemanage.model.Problem;
import com.shsh.safemanage.model.ProblemTransfer;
import com.shsh.safemanage.model.Role;
import com.shsh.safemanage.model.User;
import com.shsh.safemanage.util.Constants;
import com.shsh.safemanage.util.RequestUtil;
import com.shsh.safemanage.util.Util;

public class PostcheckReportAction {
	/**
	 * 
	 * @param request
	 * @return
	 */
	public boolean generatePostcheckSummaryReport(HttpServletRequest request) {
		Long postcheckID = 0l;
		Integer year = 0;
		Integer month = 0;
		String postcheckIDStr = (String) request.getParameter(Constants.REQUEST_PARAMETER_POSTCHECK_ID);
		try {
			postcheckID = Long.parseLong(postcheckIDStr);
		} catch (Exception e) {
			return false;
		}

		try {
			year = Integer.parseInt(request.getParameter(Constants.REQUEST_PARAMETER_YEAR));
		} catch (Exception e) {

		}

		try {
			month = Integer.parseInt(request.getParameter(Constants.REQUEST_PARAMETER_MONTH));
		} catch (Exception e) {

		}

		int monthEnd = Util.getMonthEnd(year, month);

		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();
		DepartmentDao departmentDao = DaoCreator.createDepartmentDao();

		List<Department1> shiyebuList = departmentDao.getDepartment1List(Constants.DEPARTMENT_TYPE_SHIYEBU);
		List<Department1> jiguanList = departmentDao.getDepartment1List(Constants.DEPARTMENT_TYPE_JIGUAN);

		List<Department1PostcheckMapping> mappingList = postcheckDao.searchDepartment1PostcheckMapping(null, postcheckID);

		List<Department1> department1List = new ArrayList<Department1>(shiyebuList);
		department1List.addAll(jiguanList);

		List<Long> depart1IDs = new ArrayList<Long>();
		for (Department1PostcheckMapping mapping : mappingList) {
			depart1IDs.add(mapping.getDepart1ID());
		}

		for (Iterator<Department1> iter = department1List.iterator(); iter.hasNext();) {
			Department1 d1 = iter.next();
			if (d1 != null && !depart1IDs.contains(d1.getId())) {
				iter.remove();
			}
		}

		Object[][] reportTable = new Object[department1List.size()][monthEnd + 2];
		for (int depart1Index = 0; depart1Index < department1List.size(); depart1Index++) {
			Department1 deparment1 = department1List.get(depart1Index);

			Object[] dailyReportList = postcheckDao.generateSummaryReport(year, month, monthEnd, postcheckID, deparment1.getId());

			reportTable[depart1Index][0] = deparment1.getDepartmentName();
			for (int day = 1; day <= monthEnd; day++) {
				reportTable[depart1Index][day] = dailyReportList[day];
			}
		}

		ServletContext application = request.getSession().getServletContext();
		application.setAttribute(Constants.APPLICATION_DEPARMENT1_COUNT, department1List.size());
		application.setAttribute(Constants.APPLICATION_POSTCHECK_SUMMARY_REPORT_TABLE + "_" + postcheckID + "_" + year + "_" + month,
				reportTable);
		return true;
	}

	public boolean generatePostcheckUserDailyReport(HttpServletRequest request) {
		Long postcheckID = 0l;
		Long depart1ID = 0l;
		Long userID = 0l;
		Integer year = 0;
		Integer month = 0;
		Integer day = 0;
		Integer dayStart = 0;
		Integer dayEnd = 0;

		try {
			postcheckID = Long.parseLong(request.getParameter(Constants.REQUEST_PARAMETER_POSTCHECK_ID));
		} catch (Exception e) {

		}

		try {
			depart1ID = Long.parseLong(request.getParameter(Constants.REQUEST_PARAMETER_DEPARTMENT1ID));
		} catch (Exception e) {

		}

		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();
		PostCheck postcheck = postcheckDao.getPostCheck(postcheckID);
		if (postcheck == null) {
			return false;
		}

		try {
			userID = Long.parseLong(request.getParameter(Constants.REQUEST_PARAMETER_USER_ID));
		} catch (Exception e) {

		}

		try {
			year = Integer.parseInt(request.getParameter(Constants.REQUEST_PARAMETER_YEAR));
		} catch (Exception e) {

		}

		try {
			month = Integer.parseInt(request.getParameter(Constants.REQUEST_PARAMETER_MONTH));
		} catch (Exception e) {

		}

		try {
			day = Integer.parseInt(request.getParameter(Constants.REQUEST_PARAMETER_DAY));
		} catch (Exception e) {

		}

		try {
			dayStart = Integer.parseInt(request.getParameter(Constants.REQUEST_PARAMETER_DAY_START));
		} catch (Exception e) {

		}

		try {
			dayEnd = Integer.parseInt(request.getParameter(Constants.REQUEST_PARAMETER_DAY_END));
		} catch (Exception e) {

		}

		List<PostcheckDailyReportItem> dailyReportTable = null;
		if (day > 0 && day <= 31) {
			dailyReportTable = postcheckDao.generateUserDailyReport(postcheckID, depart1ID, userID, year, month, day, day);
		} else if (dayStart > 0 && dayEnd > 0) {
			dailyReportTable = postcheckDao.generateUserDailyReport(postcheckID, depart1ID, null, year, month, dayStart, dayEnd);
		}
		request.setAttribute(Constants.REQUEST_ATTRIBUTE_POSTCHECK_USER_DAILY_REPORT, dailyReportTable);

		return true;
	}

	private boolean isAllDepartReportReady(int year, int month, Long[] depart1IDs) {
		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();
		for (Long depart1ID : depart1IDs) {
			if (!postcheckDao.hasMonthCheckSummaryReport(year, month, depart1ID)) {
				return false;
			}
		}
		return true;
	}

	private PostcheckMonthCheckSummaryReport createCorpCheckReport(int year, int month, PostCheck[] postcheckArray, Long[] depart1IDs) {
		DepartmentDao departDao = DaoCreator.createDepartmentDao();
		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();
		// Prepare postcheck list
		List<PostCheck> postcheckList = new ArrayList<PostCheck>(Arrays.asList(postcheckArray));

		PostCheck postcheck = new PostCheck();
		postcheck.setId(0l);
		postcheckList.add(postcheck);

		// Prepare depart1 list
		List<Department1> depart1List = new ArrayList<Department1>();
		for (int i = 0; i < depart1IDs.length; i++) {
			depart1List.add(departDao.getDepartment1ByID(depart1IDs[i]));
		}
		Department1 depart1 = new Department1();
		depart1.setId(0l);
		depart1List.add(depart1);

		// Prepare cellMap
		List<Problem> problemList = new ArrayList<Problem>();
		for (Long depart1ID : depart1IDs) {
			PostcheckDepartMonthCheckSummaryReport departReport = postcheckDao.getMonthCheckSummaryReport(year, month, depart1ID);
			for (PostcheckDepartMonthCheckSummaryRow row : departReport.getRowList()) {
				problemList.addAll(row.getProblemList());
			}
		}

		Map<Long, Map<Long, PostcheckMonthCheckSummaryCell>> cellMap = new HashMap<Long, Map<Long, PostcheckMonthCheckSummaryCell>>();
		for (Problem p : problemList) {
			Long postchekID = p.getPostcheckID();
			Long depart1ID = p.getDepartment1ID();
			Integer grade = p.getGrade();

			// Inner cell
			processCell(cellMap, postchekID, depart1ID, grade);

			// Bottom cell
			processCell(cellMap, 0l, depart1ID, grade);

			// Right cell
			processCell(cellMap, postchekID, 0l, grade);

			// Bottom-Right cell
			processCell(cellMap, 0l, 0l, grade);
		}

		PostcheckMonthCheckSummaryReport report = new PostcheckMonthCheckSummaryReport();
		report.setDepart1List(depart1List);
		report.setPostcheckList(postcheckList);
		report.setCellMap(cellMap);

		return null;
	}

	private PostcheckMonthCheckSummaryReport createCorpCheckReport(User sessionUser, int year, int month) {
		DepartmentDao departDao = DaoCreator.createDepartmentDao();
		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();
		UserDao userDao = DaoCreator.createUserDao();

		int monthEnd = Util.getMonthEnd(year, month);

		PostCheck[] postcheckArray = userDao.getPostcheckMappingByUserID(sessionUser.getId());

		Long[] postcheckIDs = new Long[postcheckArray.length];
		for (int i = 0; i < postcheckIDs.length; i++) {
			postcheckIDs[i] = postcheckArray[i].getId();
		}

		Long[] depart1IDs = new Long[] { Constants.SHIYEBU_ID_LIANYOU1, Constants.SHIYEBU_ID_LIANYOU2, Constants.SHIYEBU_ID_LIANYOU3,
				Constants.SHIYEBU_ID_LIANYOU4, Constants.SHIYEBU_ID_LIANYOU5, Constants.SHIYEBU_ID_HUAGONG1, Constants.SHIYEBU_ID_HUAGONG2,
				Constants.SHIYEBU_ID_HUAGONG3, Constants.SHIYEBU_ID_HUAGONG4, Constants.SHIYEBU_ID_CHUYUN1, Constants.SHIYEBU_ID_CHUYUN2,
				Constants.SHIYEBU_ID_DONGLIGUANLI, Constants.SHIYEBU_ID_SHUIWUGUANLI, Constants.SHIYEBU_ID_CHANPINFENXIFUWU };
		if (isAllDepartReportReady(year, monthEnd, depart1IDs)) {
			// Create corp report with depart report binaries.
			PostcheckMonthCheckSummaryReport corpReport = createCorpCheckReport(year, monthEnd, postcheckArray, depart1IDs);
			postcheckDao.addMonthCheckSummaryReport(corpReport);
			return corpReport;
		}

		// Prepare postcheck list
		List<PostCheck> postcheckList = new ArrayList<PostCheck>(Arrays.asList(postcheckArray));

		PostCheck postcheck = new PostCheck();
		postcheck.setId(0l);
		postcheckList.add(postcheck);

		// Prepare depart1 list
		List<Department1> depart1List = new ArrayList<Department1>();
		for (int i = 0; i < depart1IDs.length; i++) {
			depart1List.add(departDao.getDepartment1ByID(depart1IDs[i]));
		}
		Department1 depart1 = new Department1();
		depart1.setId(0l);
		depart1List.add(depart1);

		// Prepare cellMap
		List<Problem> problemList = postcheckDao.generateMonthCheckSummaryReport(postcheckIDs, depart1IDs, year, month, 1, monthEnd);
		Map<Long, Map<Long, PostcheckMonthCheckSummaryCell>> cellMap = new HashMap<Long, Map<Long, PostcheckMonthCheckSummaryCell>>();
		for (Problem p : problemList) {
			Long postchekID = p.getPostcheckID();
			Long depart1ID = p.getDepartment1ID();
			Integer grade = p.getGrade();

			// Inner cell
			processCell(cellMap, postchekID, depart1ID, grade);

			// Bottom cell
			processCell(cellMap, 0l, depart1ID, grade);

			// Right cell
			processCell(cellMap, postchekID, 0l, grade);

			// Bottom-Right cell
			processCell(cellMap, 0l, 0l, grade);
		}

		PostcheckMonthCheckSummaryReport report = new PostcheckMonthCheckSummaryReport();
		report.setDepart1List(depart1List);
		report.setPostcheckList(postcheckList);
		report.setCellMap(cellMap);

		return report;
	}

	public boolean generateMonthCheckSummaryReport(HttpServletRequest request) {
		Integer year = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_YEAR, 0);
		Integer month = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_MONTH, 0);

		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();

		PostcheckMonthCheckSummaryReport report = postcheckDao.getMonthCheckSummaryReport(year, month);
		if (report == null) {
			User sessionUser = (User) request.getSession().getAttribute(Constants.SESSION_USER);
			report = createCorpCheckReport(sessionUser, year, month);
		}

		request.setAttribute(Constants.REQUEST_ATTRIBUTE_POSTCHECK_MONTH_CHECK_SUMMARY_REPORT, report);

		return true;
	}

	private void processCell(Map<Long, Map<Long, PostcheckMonthCheckSummaryCell>> cellMap, Long postchekID, Long depart1ID, Integer grade) {
		Map<Long, PostcheckMonthCheckSummaryCell> postcheckRow = cellMap.get(postchekID);
		if (postcheckRow == null) {
			postcheckRow = new HashMap<Long, PostcheckMonthCheckSummaryCell>();
			cellMap.put(postchekID, postcheckRow);
		}

		PostcheckMonthCheckSummaryCell cell = postcheckRow.get(depart1ID);
		if (cell == null) {
			cell = new PostcheckMonthCheckSummaryCell();
			postcheckRow.put(depart1ID, cell);
		}

		processCell(cell, grade);
	}

	private void processCell(PostcheckMonthCheckSummaryCell cell, Integer grade) {
		Integer problemCount = cell.getProblemCount();
		cell.setProblemCount(problemCount == null ? 1 : ++problemCount);

		Long gradeSum = cell.getGradeSum();
		if (grade != null) {
			cell.setGradeSum(gradeSum == null ? grade : gradeSum + grade);
		}
	}

	public boolean generateDepartMonthCheckSummaryReport(HttpServletRequest request) {
		Integer year = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_YEAR, 0);
		Integer month = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_MONTH, 0);
		Long depart1ID = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_DEPARTMENT1ID, 0l);

		int monthEnd = Util.getMonthEnd(year, month);

		DepartmentDao departmentDao = DaoCreator.createDepartmentDao();
		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();

		PostcheckDepartMonthCheckSummaryReport report = postcheckDao.getMonthCheckSummaryReport(year, month, depart1ID);

		if (report == null) {
			Department1 depart1 = departmentDao.getDepartment1ByID(depart1ID);

			List<Problem> problemList = postcheckDao.generateDepartMonthCheckSummaryReport(depart1ID, year, month, 1, monthEnd);

			report = createDepartCheckReport(year, month, depart1ID, depart1.getDepartmentName(), problemList);
		}

		request.setAttribute(Constants.REQUEST_ATTRIBUTE_POSTCHECK_DEPART_MONTH_CHECK_SUMMARY_REPORT, report);

		return true;
	}

	public boolean generateCorpMonthSanweiReport(HttpServletRequest request) {
		Integer year = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_YEAR, 0);
		Integer month = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_MONTH, 0);

		boolean isSuccess = generateDepartMonthSanweiReport(request);
		if (isSuccess) {
			PostcheckMonthSanweiReport departReport = (PostcheckMonthSanweiReport) request
					.getAttribute(Constants.REQUEST_ATTRIBUTE_POSTCHECK_DEPART_MONTH_SANWEI_REPORT);
			writeCorpSanweiReport(request, departReport);
		}

		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();
		PostcheckMonthSanweiReport corpReport = postcheckDao.getCorpMonthSanweiReport(year, month);

		request.setAttribute(Constants.REQUEST_ATTRIBUTE_POSTCHECK_CORP_MONTH_SANWEI_REPORT, corpReport);
		request.getSession().setAttribute(Constants.SESSION_POSTCHECK_CORP_MONTH_SANWEI_REPORT, corpReport);
		return true;
	}

	public boolean generateDepartMonthSanweiReport(HttpServletRequest request) {
		PostcheckMonthSanweiReport report = (PostcheckMonthSanweiReport) request.getSession().getAttribute(
				Constants.SESSION_POSTCHECK_DEPART_MONTH_SANWEI_REPORT);
		if (report != null) {
			request.setAttribute(Constants.REQUEST_ATTRIBUTE_POSTCHECK_DEPART_MONTH_SANWEI_REPORT, report);
			return true;
		}

		Integer year = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_YEAR, 0);
		Integer month = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_MONTH, 0);

		int monthEnd = Util.getMonthEnd(year, month);
		User sessionUser = (User) request.getSession().getAttribute(Constants.SESSION_USER);
		Long depart1ID = sessionUser.getDepartment1ID();
		String depart1Name = sessionUser.getDepartment1Name();

		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();

		List<Problem> problemList = postcheckDao.generateDepartMonthSanweiReport(depart1ID, depart1Name, year, month, 1, monthEnd,
				Boolean.TRUE);

		report = createSanweiReport(year, month, depart1ID, depart1Name, problemList);

		request.setAttribute(Constants.REQUEST_ATTRIBUTE_POSTCHECK_DEPART_MONTH_SANWEI_REPORT, report);
		request.getSession().setAttribute(Constants.SESSION_POSTCHECK_DEPART_MONTH_SANWEI_REPORT, report);
		return true;
	}

	private PostcheckMonthSanweiReport createSanweiReport(int year, int month, Long writeDepart1ID, String writeDepart1Name,
			List<Problem> problemList) {
		PostcheckMonthSanweiReport report = new PostcheckMonthSanweiReport();

		report.setDepart1ID(writeDepart1ID);
		report.setDepart1Name(writeDepart1Name);
		report.setYear(year);
		report.setMonth(month);
		report.setPostcheckList(problemList);

		return report;
	}

	public boolean getDepartMonthCheckSummaryReport(HttpServletRequest request) {
		PostcheckDepartMonthCheckSummaryReport report = (PostcheckDepartMonthCheckSummaryReport) request.getSession().getAttribute(
				Constants.SESSION_POSTCHECK_DEPART_MONTH_CHECK_REPORT);
		if (report != null) {
			request.setAttribute(Constants.REQUEST_ATTRIBUTE_POSTCHECK_DEPART_MONTH_CHECK_SUMMARY_REPORT, report);
			return true;
		}

		Integer year = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_YEAR, 0);
		Integer month = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_MONTH, 0);

		int monthEnd = Util.getMonthEnd(year, month);

		User sessionUser = (User) request.getSession().getAttribute(Constants.SESSION_USER);
		Long depart1ID = sessionUser.getDepartment1ID();

		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();

		List<Problem> problemList = postcheckDao.generateDepartMonthCheckSummaryReport(depart1ID, year, month, 1, monthEnd, false);

		report = createDepartCheckReport(year, month, depart1ID, sessionUser.getDepartment1Name(), problemList);

		request.setAttribute(Constants.REQUEST_ATTRIBUTE_POSTCHECK_DEPART_MONTH_CHECK_SUMMARY_REPORT, report);
		request.getSession().setAttribute(Constants.SESSION_POSTCHECK_DEPART_MONTH_CHECK_REPORT, report);

		return true;
	}

	private PostcheckDepartMonthCheckSummaryReport createDepartCheckReport(int year, int month, Long depart1ID, String depart1Name,
			List<Problem> problemList) {
		UserAction theUserAction = ActionCreator.createUserAction();
		ProblemDao theProblemDao = DaoCreator.createProblemDao();

		PostcheckDepartMonthCheckSummaryReport report = new PostcheckDepartMonthCheckSummaryReport();

		report.setYear(year);
		report.setMonth(month);
		report.setDepart1ID(depart1ID);
		report.setDepart1Name(depart1Name);

		Map<Long, List<Problem>> rowMap = new HashMap<Long, List<Problem>>();
		Long gradeSum = null;
		Integer problemCount = null;
		Integer closedCount = null;
		for (Problem problem : problemList) {
			if (problemCount == null) {
				problemCount = 1;
			} else {
				problemCount++;
			}
			if (closedCount == null) {
				closedCount = 0;
			}

			if (gradeSum == null) {
				if (problem.getGrade() != null) {
					gradeSum = (long) (problem.getGrade());
				}
			} else {
				gradeSum += problem.getGrade();
			}

			if (problem.getCloseUserID() != null) {
				closedCount++;
				problem.setIsClosed(Boolean.TRUE);
			} else {
				problem.setIsClosed(Boolean.FALSE);
			}

			String userTransferFeedbackStr = theUserAction.getUserTransferFeedbackStr(theProblemDao
					.getLatestProblemTransferFeedbackByProblemID(problem.getId()));
			problem.setUserTransferFeedbackStr(userTransferFeedbackStr);

			List<Problem> rowProblemList = rowMap.get(problem.getPostcheckID());
			if (rowProblemList == null) {
				rowProblemList = new ArrayList<Problem>();
				rowMap.put(problem.getPostcheckID(), rowProblemList);
			}

			rowProblemList.add(problem);
		}

		List<PostcheckDepartMonthCheckSummaryRow> rowList = new ArrayList<PostcheckDepartMonthCheckSummaryRow>();
		for (Map.Entry<Long, List<Problem>> entry : rowMap.entrySet()) {
			PostcheckDepartMonthCheckSummaryRow row = new PostcheckDepartMonthCheckSummaryRow();
			PostCheck postcheck = new PostCheck();
			postcheck.setId(entry.getKey());
			postcheck.setCheckName(entry.getValue().get(0).getPostcheckName());

			row.setPostcheck(postcheck);
			row.setProblemList(entry.getValue());

			rowList.add(row);
		}

		report.setRowList(rowList);
		report.setProblemCount(problemCount);
		report.setClosedCount(closedCount);
		report.setGradeSum(gradeSum);

		return report;
	}

	private boolean refreshMonthSanweiReport(HttpServletRequest request, PostcheckMonthSanweiReport report) {
		String paramJSON = request.getParameter(Constants.REQUEST_PARAMETER_PARAM_JSON);
		JSONObject jsonObj = null;
		try {
			jsonObj = new JSONObject(paramJSON);

			Long problemID = null;
			if (JSONObject.getNames(jsonObj) == null) {
				return true;
			}
			for (String key : JSONObject.getNames(jsonObj)) {
				String value = jsonObj.getString(key);

				if (key.indexOf("SanweiTrue") >= 0) {
					problemID = Util.extractEntityID(key, "SanweiTrue");
					if (Boolean.parseBoolean(value)) {
						report.setIsSanwei(problemID, true);
					}
				} else if (key.indexOf("SanweiFalse") >= 0) {
					problemID = Util.extractEntityID(key, "SanweiFalse");
					if (Boolean.parseBoolean(value)) {
						report.setIsSanwei(problemID, false);
					}
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	public boolean writeCorpMonthSanweiReport(HttpServletRequest request) {
		HttpSession session = request.getSession();
		User user = (User) session.getAttribute(Constants.SESSION_USER);

		RoleDao roleDao = DaoCreator.createRoleDao();
		int processMethod = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_PROCESS_METHOD, 0);

		if (!roleDao.hasRight(Constants.AUTH_TYPE_POSTCHECK_MONTH_CORPSANWEI_REPORT, user.getRoleID(), processMethod)) {
			switch (processMethod) {
			case Constants.PROCESS_METHOD_CLOSE:
				request.setAttribute(Constants.REQUEST_ATTRIBUTE_ERROR, Constants.ERROR_KEY_IS_NOT_AUTHORIZED_CLOSE);
				break;
			case Constants.PROCESS_METHOD_ESCALATE:
				request.setAttribute(Constants.REQUEST_ATTRIBUTE_ERROR, Constants.ERROR_KEY_IS_NOT_AUTHORIZED_SANWEI_ESCALATE);
				break;
			}
			return false;
		}

		PostcheckMonthSanweiReport report = (PostcheckMonthSanweiReport) session
				.getAttribute(Constants.SESSION_POSTCHECK_CORP_MONTH_SANWEI_REPORT);
		if (report == null) {
			return false;
		}

		if (!refreshMonthSanweiReport(request, report)) {
			return false;
		}
		refreshCorpSanweiReport(report);

		boolean isSuccess = this.createNewProblem(request, user.getDepartment1ID(),
				Constants.PROBLEM_TYPE_POSTCHECK_MONTH_CORPSANWEI_REPORT);
		Problem newProblem = (Problem) request.getAttribute(Constants.REQUEST_ATTRIBUTE_NEW_PROBLEM);
		request.removeAttribute(Constants.REQUEST_ATTRIBUTE_NEW_PROBLEM);
		if (!isSuccess) {
			return false;
		}

		report.setProblemID(newProblem.getId());

		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();
		ProblemDao problemDao = DaoCreator.createProblemDao();
		boolean isSuccess2 = postcheckDao.updateCorpMonthSanweiReport(report);
		if (!isSuccess2) {
			problemDao.deleteProblemByIDList(new Long[] { newProblem.getId() });
			return false;
		}

		session.removeAttribute(Constants.SESSION_POSTCHECK_CORP_MONTH_SANWEI_REPORT);
		return isSuccess2;
	}

	public boolean feedbackCorpMonthSanweiReport(HttpServletRequest request) {
		HttpSession session = request.getSession();
		RoleDao roleDao = DaoCreator.createRoleDao();
		int processMethod = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_PROCESS_METHOD, 0);

		User sessionUser = (User) session.getAttribute(Constants.SESSION_USER);
		if (!roleDao.hasRight(Constants.AUTH_TYPE_POSTCHECK_MONTH_CORPSANWEI_REPORT, sessionUser.getRoleID(), processMethod)) {
			switch (processMethod) {
			case Constants.PROCESS_METHOD_CLOSE:
				request.setAttribute(Constants.REQUEST_ATTRIBUTE_ERROR, Constants.ERROR_KEY_IS_NOT_AUTHORIZED_CLOSE);
				break;
			case Constants.PROCESS_METHOD_ESCALATE:
				request.setAttribute(Constants.REQUEST_ATTRIBUTE_ERROR, Constants.ERROR_KEY_IS_NOT_AUTHORIZED_SANWEI_ESCALATE);
				break;
			}
			return false;
		}

		PostcheckMonthSanweiReport report = (PostcheckMonthSanweiReport) session
				.getAttribute(Constants.SESSION_POSTCHECK_CORP_MONTH_SANWEI_REPORT);
		if (report == null) {
			return false;
		}

		if (!refreshMonthSanweiReport(request, report)) {
			return false;
		}
		refreshCorpSanweiReport(report);

		Long problemID = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_ID, 0l);

		ProblemDao problemDao = DaoCreator.createProblemDao();
		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();

		problemDao.updateProblem(problemID, "PROCESS_STATUS", Constants.PROBLEM_STATUS_CLOSE);
		problemDao.updateProblem(problemID, "CLOSE_USER_ID", sessionUser.getId());
		problemDao.updateProblem(problemID, "CLOSE_TIME", Calendar.getInstance(), Calendar.class);

		boolean isSuccess2 = postcheckDao.updateMonthSanweiReport(problemID, report);
		if (!isSuccess2) {
			return false;
		}

		session.removeAttribute(Constants.SESSION_POSTCHECK_CORP_MONTH_SANWEI_REPORT);
		return isSuccess2;
	}

	public boolean feedbackDepartMonthSanweiReport(HttpServletRequest request) {
		HttpSession session = request.getSession();
		User sessionUser = (User) session.getAttribute(Constants.SESSION_USER);
		int processMethod = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_PROCESS_METHOD, 0);

		RoleDao roleDao = DaoCreator.createRoleDao();
		if (!roleDao.hasRight(Constants.AUTH_TYPE_POSTCHECK_MONTH_SANWEI_REPORT, sessionUser.getRoleID(), processMethod)) {
			switch (processMethod) {
			case Constants.PROCESS_METHOD_CLOSE:
				request.setAttribute(Constants.REQUEST_ATTRIBUTE_ERROR, Constants.ERROR_KEY_IS_NOT_AUTHORIZED_CLOSE);
				break;
			case Constants.PROCESS_METHOD_ESCALATE:
				request.setAttribute(Constants.REQUEST_ATTRIBUTE_ERROR, Constants.ERROR_KEY_IS_NOT_AUTHORIZED_SANWEI_ESCALATE);
				break;
			}
			return false;
		}
		PostcheckMonthSanweiReport report = (PostcheckMonthSanweiReport) session
				.getAttribute(Constants.SESSION_POSTCHECK_DEPART_MONTH_SANWEI_REPORT);
		if (report == null) {
			return false;
		}

		if (!refreshMonthSanweiReport(request, report)) {
			return false;
		}

		Long problemID = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_ID, 0l);

		ProblemDao problemDao = DaoCreator.createProblemDao();
		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();

		Problem problem = problemDao.getProblemByID(problemID);

		WriteProblemAction writeProblemAction = ActionCreator.createWriteProblemAction();

		if (!writeProblemAction.canbeProcessed(request, Constants.PROBLEM_TYPE_POSTCHECK_MONTH_SANWEI_REPORT, sessionUser, problem)) {
			return false;
		}

		boolean isSuccess = writeProblemAction.feedbackProblem(request);
		if (!isSuccess) {
			return false;
		}

		String problemTitle = request.getParameter(Constants.REQUEST_PARAMETER_PROBLEM_TITLE);
		String problemContent = request.getParameter(Constants.REQUEST_PARAMETER_PROBLEM_CONTENT);

		if (!Util.isNullOrEmpty(problemTitle)) {
			problemTitle = Util.isoToUTF8(problemTitle);
		}

		if (!Util.isNullOrEmpty(problemContent)) {
			problemContent = Util.isoToUTF8(problemContent);
		}

		boolean isSuccess2 = postcheckDao.updateMonthSanweiReport(problemID, report);
		if (!isSuccess2) {
			return false;
		}

		if (processMethod == Constants.PROCESS_METHOD_CLOSE) {
			isSuccess2 = writeCorpSanweiReport(request, report);
			if (!isSuccess2) {
				return false;
			}
		}

		session.removeAttribute(Constants.SESSION_POSTCHECK_DEPART_MONTH_SANWEI_REPORT);
		return isSuccess2;
	}

	private void refreshCorpSanweiReport(PostcheckMonthSanweiReport corpReport) {

		Map<Long, Integer> shiyebuTable = corpReport.getShiyebuTable();
		Map<Long, Integer> chushiTable = corpReport.getChushiTable();

		for (Long depart1ID : shiyebuTable.keySet()) {
			shiyebuTable.put(depart1ID, 0);
		}
		for (Long depart1ID : chushiTable.keySet()) {
			chushiTable.put(depart1ID, 0);
		}

		for (Problem p : corpReport.getPostcheckList()) {

			Long depart1ID = p.getDepartment1ID();
			Map<Long, Integer> targetTable = null;
			if (shiyebuTable.containsKey(depart1ID)) {
				targetTable = shiyebuTable;
			} else if (chushiTable.containsKey(depart1ID)) {
				targetTable = chushiTable;
			}

			if (targetTable == null) {
				continue;
			}
			if (p.getIsSanwei() != null && p.getIsSanwei()) {
				int isSanweiCount = targetTable.get(depart1ID);
				isSanweiCount++;
				targetTable.put(depart1ID, isSanweiCount);
			}
		}

	}

	private void refreshCorpSanweiReport(PostcheckMonthSanweiReport corpReport, PostcheckMonthSanweiReport departReport) {
		DepartmentDao departmentDao = DaoCreator.createDepartmentDao();
		ProblemDao problemDao = DaoCreator.createProblemDao();

		Long tmpProblemID = null;
		if (departReport.getProblemID() != null) {
			tmpProblemID = departReport.getProblemID();
		} else {
			tmpProblemID = corpReport.getProblemID();
		}
		if (tmpProblemID != null) {
			Problem departProblem = problemDao.getProblemByID(tmpProblemID);
			if (departProblem != null) {
				Problem tmpProblem = new Problem();
				tmpProblem.setId(departProblem.getId());
				tmpProblem.setWriterDepartment1ID(departProblem.getDepartment1ID());
				tmpProblem.setWriterDepartment1Name(departProblem.getDepartment1Name());
				tmpProblem.setCloseUserName(departProblem.getWriteUserName());
				tmpProblem.setCloseTime(departProblem.getCloseTime());
				corpReport.getDepartSanweiList().put(tmpProblem.getWriterDepartment1ID(), tmpProblem);
			}
		}

		List<Problem> corpPostcheckList = corpReport.getPostcheckList();
		List<Problem> departPostcheckList = departReport.getPostcheckList();
		if (corpPostcheckList == null) {
			corpPostcheckList = new ArrayList<Problem>();
			corpReport.setPostcheckList(corpPostcheckList);
		}
		corpPostcheckList.addAll(departPostcheckList);

		Map<Long, Department1> shiyebuList = corpReport.getShiyebuList();
		Map<Long, Department1> chushiList = corpReport.getChushiList();
		Map<Long, Integer> shiyebuTable = corpReport.getShiyebuTable();
		Map<Long, Integer> chushiTable = corpReport.getChushiTable();

		if (shiyebuList == null) {
			shiyebuList = new LinkedHashMap<Long, Department1>();
			shiyebuTable = new HashMap<Long, Integer>();

			List<Department1> depart1List = departmentDao.getDepartment1List(Constants.DEPARTMENT_TYPE_SHIYEBU);
			for (Department1 depart1 : depart1List) {
				shiyebuList.put(depart1.getId(), depart1);
				shiyebuTable.put(depart1.getId(), 0);
			}

			corpReport.setShiyebuTable(shiyebuTable);
			corpReport.setShiyebuList(shiyebuList);
		}
		if (chushiList == null) {
			chushiList = new LinkedHashMap<Long, Department1>();
			chushiTable = new HashMap<Long, Integer>();

			for (Long depart1ID : Constants.CHUSHI_IDS_POSTCHECKREPORT) {
				Department1 depart1 = departmentDao.getDepartment1ByID(depart1ID);
				chushiList.put(depart1.getId(), depart1);
				chushiTable.put(depart1.getId(), 0);
			}

			corpReport.setChushiList(chushiList);
			corpReport.setChushiTable(chushiTable);
		}

		for (Problem p : departPostcheckList) {
			Long depart1ID = p.getDepartment1ID();

			Map<Long, Integer> targetTable = null;
			if (shiyebuTable.containsKey(depart1ID)) {
				targetTable = shiyebuTable;
			} else if (chushiTable.containsKey(depart1ID)) {
				targetTable = chushiTable;
			}

			if (targetTable == null) {
				continue;
			}

			int isSanweiCount = targetTable.get(depart1ID);
			if (p.getIsSanwei() != null && p.getIsSanwei()) {
				isSanweiCount++;
			}
			targetTable.put(depart1ID, isSanweiCount);
		}

	}

	private boolean writeCorpSanweiReportTobeProcessed(HttpServletRequest request, PostcheckMonthSanweiReport departReport) {
		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();
		ProblemDao problemDao = DaoCreator.createProblemDao();

		int year = departReport.getYear();
		int month = departReport.getMonth();

		boolean needNewProblem = false;
		PostcheckMonthSanweiReport corpReport = postcheckDao.getCorpMonthSanweiReport(year, month);
		if (corpReport == null) {
			needNewProblem = true;
			corpReport = new PostcheckMonthSanweiReport();
			corpReport.setYear(year);
			corpReport.setMonth(month);
		}

		if (!needNewProblem) {
			// Cannot refresh corp table when it is closed.
			Long corpProblemID = corpReport.getProblemID();
			if (corpProblemID == null) {
				return false;
			}
			Problem corpProblem = problemDao.getProblemByID(corpProblemID);
			if (corpProblem.getProcessStatus() >= Constants.PROBLEM_STATUS_CLOSE) {
				return true;
			}
		}

		this.refreshCorpSanweiReport(corpReport, departReport);

		if (!needNewProblem) {
			postcheckDao.updateCorpMonthSanweiReport(corpReport);
			return true;
		}

		boolean isSuccess = this.createNewProblemForCorpSanweiReport(request);
		Problem newProblem = (Problem) request.getAttribute(Constants.REQUEST_ATTRIBUTE_NEW_PROBLEM);
		request.removeAttribute(Constants.REQUEST_ATTRIBUTE_NEW_PROBLEM);
		if (!isSuccess) {
			return false;
		}

		corpReport.setProblemID(newProblem.getId());
		isSuccess = postcheckDao.addCorpMonthSanweiReport(newProblem.getId(), corpReport);

		return true;
	}

	private boolean writeCorpSanweiReport(HttpServletRequest request, PostcheckMonthSanweiReport departReport) {
		HttpSession session = request.getSession();
		User sessionUser = (User) session.getAttribute(Constants.SESSION_USER);
		Calendar cal = Calendar.getInstance();
		for (Problem p : departReport.getPostcheckList()) {
			p.setCloseUserID(sessionUser.getId());
			p.setCloseUserName(sessionUser.getName());
			p.setCloseTime(cal);
		}

		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();
		ProblemDao problemDao = DaoCreator.createProblemDao();

		int year = departReport.getYear();
		int month = departReport.getMonth();

		PostcheckMonthSanweiReport corpReport = postcheckDao.getCorpMonthSanweiReport(year, month);
		boolean isNewReport = false;
		if (corpReport == null) {
			isNewReport = true;
			corpReport = new PostcheckMonthSanweiReport();
			corpReport.setYear(year);
			corpReport.setMonth(month);
		}

		Long corpProblemID = corpReport.getProblemID();
		if (corpProblemID != null) {
			// Cannot refresh corp table when it is closed.
			Problem corpProblem = problemDao.getProblemByID(corpProblemID);
			if (corpProblem.getProcessStatus() >= Constants.PROBLEM_STATUS_CLOSE) {
				return true;
			}
		}

		this.refreshCorpSanweiReport(corpReport, departReport);

		if (!isNewReport) {
			postcheckDao.updateCorpMonthSanweiReport(corpReport);
		} else {
			postcheckDao.addCorpMonthSanweiReport(null, corpReport);
		}

		return true;
	}

	private boolean refreshMonthCheckReport(HttpServletRequest request, PostcheckDepartMonthCheckSummaryReport report) {
		int closedCount = 0;
		String paramJSON = request.getParameter(Constants.REQUEST_PARAMETER_PARAM_JSON);
		JSONObject jsonObj = null;
		try {
			jsonObj = new JSONObject(paramJSON);

			Long problemID = null;
			if (JSONObject.getNames(jsonObj) == null) {
				return true;
			}
			for (String key : JSONObject.getNames(jsonObj)) {
				String value = jsonObj.getString(key);

				if (key.indexOf("CloseFeedback") >= 0) {
					problemID = Util.extractEntityID(key, "CloseFeedback");

					report.setCloseFeedback(problemID, value);
				} else if (key.indexOf("ClosedTrue") >= 0) {
					problemID = Util.extractEntityID(key, "ClosedTrue");
					if (Boolean.parseBoolean(value)) {
						report.setIsClosed(problemID, true);
						closedCount++;
					}
				} else if (key.indexOf("ClosedFalse") >= 0) {
					problemID = Util.extractEntityID(key, "ClosedFalse");
					if (Boolean.parseBoolean(value)) {
						report.setIsClosed(problemID, false);
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		report.setClosedCount(closedCount);

		return true;
	}

	public boolean feedbackDepartMontchCheckSummaryReport(HttpServletRequest request) {
		HttpSession session = request.getSession();
		User sessionUser = (User) session.getAttribute(Constants.SESSION_USER);
		int processMethod = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_PROCESS_METHOD, 0);

		RoleDao roleDao = DaoCreator.createRoleDao();
		if (!roleDao.hasRight(Constants.AUTH_TYPE_POSTCHECK_MONTH_CHECK_REPORT, sessionUser.getRoleID(), processMethod)) {
			switch (processMethod) {
			case Constants.PROCESS_METHOD_CLOSE:
				request.setAttribute(Constants.REQUEST_ATTRIBUTE_ERROR, Constants.ERROR_KEY_IS_NOT_AUTHORIZED_CLOSE);
				break;
			case Constants.PROCESS_METHOD_ESCALATE:
				request.setAttribute(Constants.REQUEST_ATTRIBUTE_ERROR, Constants.ERROR_KEY_IS_NOT_AUTHORIZED_ESCALATE);
				break;
			}
			return false;
		}
		PostcheckDepartMonthCheckSummaryReport report = (PostcheckDepartMonthCheckSummaryReport) session
				.getAttribute(Constants.SESSION_POSTCHECK_DEPART_MONTH_CHECK_REPORT);
		if (report == null) {
			return false;
		}

		if (!refreshMonthCheckReport(request, report)) {
			return false;
		}

		Long problemID = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_ID, 0l);

		ProblemDao problemDao = DaoCreator.createProblemDao();
		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();

		Problem problem = problemDao.getProblemByID(problemID);

		WriteProblemAction writeProblemAction = ActionCreator.createWriteProblemAction();

		if (!writeProblemAction.canbeProcessed(request, Constants.PROBLEM_TYPE_POSTCHECK_MONTH_CHECK_REPORT, sessionUser, problem)) {
			return false;
		}

		boolean isSuccess = writeProblemAction.feedbackProblem(request);
		if (!isSuccess) {
			return false;
		}

		String problemTitle = request.getParameter(Constants.REQUEST_PARAMETER_PROBLEM_TITLE);
		String problemContent = request.getParameter(Constants.REQUEST_PARAMETER_PROBLEM_CONTENT);

		if (!Util.isNullOrEmpty(problemTitle)) {
			problemTitle = Util.isoToUTF8(problemTitle);
		}

		if (!Util.isNullOrEmpty(problemContent)) {
			problemContent = Util.isoToUTF8(problemContent);
		}

		boolean isSuccess2 = postcheckDao.updateMonthCheckSummaryReport(problemID, report);

		session.removeAttribute(Constants.SESSION_POSTCHECK_DEPART_MONTH_CHECK_REPORT);
		return isSuccess2;
	}

	private boolean createNewProblemForCorpSanweiReport(HttpServletRequest request) {
		HttpSession session = request.getSession();
		ProblemDao problemDao = DaoCreator.createProblemDao();
		UserDao userDao = DaoCreator.createUserDao();

		Long depart1ID = Constants.DEPARTMENT1_ID_QIYEGUANLICHU;

		WriteProblemAction writeProblemAction = ActionCreator.createWriteProblemAction();

		boolean isSuccess = true;

		User user = null;

		List<User> kaohekeyuanList = userDao.getUserListByDepartment2ID(Constants.DEPARTMENT2_ID_KAOHEKE);

		List<Long> informedUserIDList = new ArrayList<Long>();
		for (User u : kaohekeyuanList) {
			informedUserIDList.add(u.getId());
		}

		if (kaohekeyuanList.size() == 0) {
			return true;
		}

		user = kaohekeyuanList.get(0);

		String problemTitle = request.getParameter(Constants.REQUEST_PARAMETER_PROBLEM_TITLE);
		String problemContent = null;
		String problemZhenggai = null;
		Long problemEquipID = 0L;

		Problem problem = new Problem();
		problem.setDepartment1ID(depart1ID);
		problem.setEquipmentID(problemEquipID);
		problem.setProblemContent(problemContent);
		problem.setProblemTitle(Util.isoToUTF8(problemTitle));
		problem.setProblemZhenggai(problemZhenggai);
		problem.setProcessStatus(Constants.PROBLEM_STATUS_KEYUAN);
		problem.setWriteTime(Calendar.getInstance());
		problem.setWriteUserID(user.getId());
		problem.setWriterDepartment1ID(user.getDepartment1ID());
		problem.setWriterDepartment2ID(user.getDepartment2ID());

		request.setAttribute(Constants.REQUEST_ATTRIBUTE_NEW_PROBLEM, problem);

		isSuccess = problemDao.addProblem(problem);
		Long problemID = problem.getId();

		problemDao.updateProblem(problemID, "PROBLEM_TYPE", Constants.PROBLEM_TYPE_POSTCHECK_MONTH_CORPSANWEI_REPORT);

		// transfer to users
		writeProblemAction.addTransferInManageGroups(session, user, problem, informedUserIDList, false, true, null);

		return isSuccess;
	}

	private boolean createNewProblem(HttpServletRequest request, Long depart1ID, int problemType) {
		HttpSession session = request.getSession();
		WriteProblemAction writeProblemAction = ActionCreator.createWriteProblemAction();

		boolean isSuccess;

		User user = (User) session.getAttribute(Constants.SESSION_USER);

		String problemTitle = request.getParameter(Constants.REQUEST_PARAMETER_PROBLEM_TITLE);
		String problemContent = null;
		String problemZhenggai = null;
		Long problemEquipID = 0L;

		Problem problem = new Problem();
		problem.setDepartment1ID(depart1ID);
		problem.setEquipmentID(problemEquipID);
		problem.setProblemContent(problemContent);
		problem.setProblemTitle(Util.isoToUTF8(problemTitle));
		problem.setProblemZhenggai(problemZhenggai);
		problem.setProcessStatus(Constants.PROBLEM_STATUS_ZUZHANG_ZHUANGZHIZHANG);
		problem.setWriteTime(Calendar.getInstance());
		problem.setWriteUserID(user.getId());
		problem.setWriterDepartment1ID(user.getDepartment1ID());
		problem.setWriterDepartment2ID(user.getDepartment2ID());

		request.setAttribute(Constants.REQUEST_ATTRIBUTE_NEW_PROBLEM, problem);

		ProblemDao problemDao = DaoCreator.createProblemDao();

		isSuccess = problemDao.addProblem(problem);
		Long problemID = problem.getId();

		problemDao.updateProblem(problemID, "PROBLEM_TYPE", problemType);

		// transfer to users
		List<Long> informedUserIDList = new ArrayList<Long>();
		informedUserIDList.add(user.getId());
		writeProblemAction.addTransferInManageGroups(session, user, problem, informedUserIDList, false, true, null);

		isSuccess = writeProblemAction.createProblemTransfer(request, problem.getId());
		if (!isSuccess) {
			request.setAttribute(Constants.REQUEST_ATTRIBUTE_ERROR, Constants.ERROR_KEY_WRITE_FAIL);
			problemDao.deleteProblemByIDList(new Long[] { problemID });
			return false;
		}
		ProblemTransfer transfer = problemDao.getProblemTransfer(user.getId(), problemID, user.getId());
		isSuccess = writeProblemAction.feedbackProblem(request, String.valueOf(problemID), String.valueOf(transfer.getId()));
		if (!isSuccess) {
			problemDao.deleteProblemByIDList(new Long[] { problemID });
			// Feedback already set error information.
			return false;
		}

		return true;
	}

	private void createShiyebuQualityReport(PostcheckMonthQualityReport report, int year, int month) {
		Map<Long, Department1> depart1List = report.getShiyebuList();
		Map<Long, PostcheckMonthQualityReport.ShiyebuReport> shiyebuReportMap = report.getShiyebuReportMap();

		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();
		int monthEnd = Util.getMonthEnd(year, month);
		int[] previous = Util.getPreviousYearMonth(year, month);
		int[] currentTime = Util.getCurrentDate();

		DepartmentDao departDao = DaoCreator.createDepartmentDao();
		PostcheckMonthQualityReport previousReport = postcheckDao.getMonthQualityReport(previous[0], previous[1]);

		PostcheckMonthSanweiReport sanweiReport = postcheckDao.getCorpMonthSanweiReport(year, month);

		for (Long shiyebuID : depart1List.keySet()) {
			// For each shiyebu, each columns in shiyebu quality table.

			PostcheckMonthQualityReport.ShiyebuReport previousShiyebuReport = previousReport == null ? null : previousReport
					.getShiyebuReportMap().get(shiyebuID);
			// Find the check report
			PostcheckDepartMonthCheckSummaryReport departCheckReport = postcheckDao.getMonthCheckSummaryReport(year, month, shiyebuID);
			if (departCheckReport == null) {
				if (year == currentTime[0] && month == currentTime[1]) {
					// current month
					List<Problem> problemList = postcheckDao.generateDepartMonthCheckSummaryReport(shiyebuID, year, month, 1, monthEnd);

					Department1 shiyebu = departDao.getDepartment1ByID(shiyebuID);
					departCheckReport = createDepartCheckReport(year, month, shiyebuID, shiyebu.getDepartmentName(), problemList);
					if (departCheckReport.getProblemCount() == null) {
						departCheckReport.setProblemCount(0);
					}
					if (departCheckReport.getClosedCount() == null) {
						departCheckReport.setClosedCount(0);
					}
				} else {
					continue;
				}
			}

			PostcheckMonthQualityReport.ShiyebuReport departReport = report.new ShiyebuReport();

			// set worker count
			departReport.setWorkerCount(previousShiyebuReport == null ? null : previousShiyebuReport.getWorkerCount());
			// set unit count
			departReport.setUnitCount(previousShiyebuReport == null ? null : previousShiyebuReport.getUnitCount());

			// Calculate mantime need
			if (departReport.getWorkerCount() != null) {
				departReport.setMantimeNeed(report.getWorkingDay() * departReport.getWorkerCount());
			}
			// Calculate check unit need
			if (departReport.getUnitCount() != null) {
				departReport.setCheckUnitCountNeed(report.getWorkingDay() * departReport.getUnitCount() * 5);
			}

			// Calculate mantime and check unit count from DB
			departReport.setMantimeReal(postcheckDao.getShiyebuMantime(year, month, 1, monthEnd, shiyebuID));
			departReport.setCheckUnitCountReal(postcheckDao.getCheckUnitCount(year, month, 1, monthEnd, shiyebuID));

			// Get sanwei count from corp sanwei report
			Integer isSanweiCount = null;
			if (sanweiReport != null && sanweiReport.getShiyebuTable() != null) {
				isSanweiCount = sanweiReport.getShiyebuTable().get(shiyebuID);
			}
			departReport.setIsSanweiCount(isSanweiCount);

			// Get corp problem count and closed count from depart check report
			Integer corpProblemCount = departCheckReport.getProblemCount();
			Integer isClosedCount = departCheckReport.getClosedCount();

			departReport.setCorpProblemCount(corpProblemCount);
			departReport.setIsClosedCount(isClosedCount);

			// calculate closed rate and set
			Integer closedRate = (int) (isClosedCount.intValue() * 100 / (corpProblemCount.intValue() * 1.0) * 20);
			departReport.setClosedRate(closedRate);

			// init postcheck problem count map
			int allSelfCheckSum = 0;
			Map<Long, ShiyebuReportCell> problemCountMap = departReport.getProblemCountMap();
			for (Long postcheckID : report.getPostcheckList().keySet()) {
				ShiyebuReportCell departReportCell = problemCountMap.get(postcheckID);
				if (departReportCell == null) {
					// create new cell
					departReportCell = departReport.new ShiyebuReportCell();
					departReportCell.setChushiCheckCount(0);
					departReportCell.setChushiCheckGrade(0);
					departReportCell.setSelfCheckCount(0);
					departReportCell.setSelfcheckedGrade(0);
				}
				problemCountMap.put(postcheckID, departReportCell);
			}

			Map<Long, Integer> bigSelfCheckSumMap = new HashMap<Long, Integer>();
			Map<Long, Integer> bigChushiCheckMap = new HashMap<Long, Integer>();
			for (PostcheckDepartMonthCheckSummaryRow row : departCheckReport.getRowList()) {
				Long rowPostcheckID = row.getPostcheck().getId();
				if (!report.getPostcheckList().containsKey(rowPostcheckID)) {
					// not in the 9 postcheck
					continue;
				}

				ShiyebuReportCell departReportCell = problemCountMap.get(rowPostcheckID);
				if (departReportCell == null) {
					// create new cell
					departReportCell = departReport.new ShiyebuReportCell();
				}
				problemCountMap.put(rowPostcheckID, departReportCell);

				// get problem count of this postcheck
				Integer chushiCheckCount = row.getProblemList().size();
				// calculate problem grade of this postcheck
				Integer chushiCheckGrade = 0;
				for (Problem p : row.getProblemList()) {
					chushiCheckGrade += p.getGrade();
				}
				departReportCell.setChushiCheckGrade(chushiCheckGrade);
				departReportCell.setChushiCheckCount(chushiCheckCount);

				// Get self check postcheck problems.
				Integer selfCheckCount = 0;
				Integer selfCheckGrade = 0;
				List<Problem> problemList = postcheckDao.getSelfCheckProblem(year, month, 1, monthEnd, shiyebuID, rowPostcheckID);
				selfCheckCount = problemList.size();
				for (Problem p : problemList) {
					if (p.getGrade() != null) {
						selfCheckGrade += p.getGrade();
					}
				}
				allSelfCheckSum += selfCheckCount;
				departReportCell.setSelfCheckCount(selfCheckCount);
				departReportCell.setSelfcheckedGrade(selfCheckGrade);

				// Set chushi check count and grade

				Long bigPostcheckID = PostcheckMonthQualityReport.BIG_POSTCHECK_MAPPING.get(rowPostcheckID);
				Integer bigSelfCheckCount = bigSelfCheckSumMap.get(bigPostcheckID);
				Integer bigChushiCheckCount = bigChushiCheckMap.get(bigPostcheckID);
				if (bigSelfCheckCount == null) {
					bigSelfCheckCount = selfCheckCount;
				} else {
					bigSelfCheckCount += selfCheckCount;
				}

				if (bigChushiCheckCount == null) {
					bigChushiCheckCount = chushiCheckCount;
				} else {
					bigChushiCheckCount += chushiCheckCount;
				}

				bigSelfCheckSumMap.put(bigPostcheckID, bigSelfCheckCount);
				bigChushiCheckMap.put(bigPostcheckID, bigChushiCheckCount);
			}
			shiyebuReportMap.put(shiyebuID, departReport);

			// daily finish rate
			if (departReport.getCheckUnitCountNeed() != null) {
				int dailyFinishRate = (int) (departReport.getCheckUnitCountReal() / (departReport.getCheckUnitCountNeed() * 1.0) * 10 * 100);
				if (dailyFinishRate > 10 * 100) {
					dailyFinishRate = 10 * 100;
				}
				departReport.setDailyFinishRate(dailyFinishRate);
			}

			// Daily partake rate
			if (departReport.getMantimeNeed() != null) {
				int dailyPartakeRate = (int) (departReport.getMantimeReal() / (departReport.getMantimeNeed() * 1.0) * 10 * 100);
				if (dailyPartakeRate > 10 * 100) {
					dailyPartakeRate = 10 * 100;
				}
				departReport.setDailyPartakeRate(dailyPartakeRate);
			}

			// Self check rate
			Integer selfCheckRate = null;
			if (allSelfCheckSum == 0) {
				selfCheckRate = 10 * 100;
			} else {
				selfCheckRate = (allSelfCheckSum / corpProblemCount * 1.0) >= 5 ? 10 * 100 : 0;
			}
			departReport.setSlefCheckRate(selfCheckRate);

			// init coverage map
			Map<Long, Integer> coverageMap = departReport.getCoverageMap();
			for (Long bigPostcheckID : PostcheckMonthQualityReport.BIG_POSTCHECK_MAPPING.values()) {
				Integer coverageRate = coverageMap.get(bigPostcheckID);

				Integer bigSelfCheckCount = bigSelfCheckSumMap.get(bigPostcheckID);
				Integer bigChushiCheckCount = bigChushiCheckMap.get(bigPostcheckID);

				if (bigSelfCheckCount == null) {
					bigSelfCheckCount = 0;
				}
				if (bigChushiCheckCount == null) {
					bigChushiCheckCount = 0;
				}

				if (bigChushiCheckCount.intValue() == 0) {
					coverageRate = 6 * 100;
				} else {
					coverageRate = bigSelfCheckCount / (bigChushiCheckCount * 1.0) >= 5 ? 6 * 100 : 0;
				}

				coverageMap.put(bigPostcheckID, coverageRate);
			}

			// Sanwei rate
			if (isSanweiCount != null) {
				Integer sanweiRate = (isSanweiCount * 10 + 20) * 100;
				departReport.setSanwei(sanweiRate);
			}

			// calculate postcheck assess grade
		}
	}

	private void createChushiQualityReport(PostcheckMonthQualityReport report, int year, int month) {
		Map<Long, Department1> chushiList = report.getChushiList();
		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();
		int currentMonthEnd = Util.getMonthEnd(year, month);
		int[] previous = Util.getPreviousYearMonth(year, month);

		int monthIndex = Util.getMonthIndexInSeason(month);

		// Prepare chushi problem count.
		Map<Long, Integer> chushiProblemCountMap = new HashMap<Long, Integer>();
		Map<Long, Integer> chushiGradeSumMap = new HashMap<Long, Integer>();
		for (ShiyebuReport shiyebuReport : report.getShiyebuReportMap().values()) {
			for (Long postcheckID : shiyebuReport.getProblemCountMap().keySet()) {
				ShiyebuReportCell cell = shiyebuReport.getProblemCountMap().get(postcheckID);
				if (cell == null) {
					continue;
				}
				Long chushiID = PostcheckMonthQualityReport.POSTCHECK_CHUSHI_MAPPING.get(postcheckID);
				if (chushiID == null) {
					continue;
				}

				Integer chushiProblemCount = chushiProblemCountMap.get(chushiID);
				if (chushiProblemCount == null) {
					chushiProblemCount = cell.getChushiCheckCount();
				} else if (cell.getChushiCheckCount() != null) {
					chushiProblemCount += cell.getChushiCheckCount();
				}
				chushiProblemCountMap.put(chushiID, chushiProblemCount);

				Integer chushiGradeSum = chushiGradeSumMap.get(chushiID);
				if (chushiGradeSum == null) {
					chushiGradeSum = cell.getChushiCheckGrade();
				} else if (cell.getChushiCheckGrade() != null) {
					chushiGradeSum += cell.getChushiCheckGrade();
				}
				chushiGradeSumMap.put(chushiID, chushiGradeSum);
			}
		}

		PostcheckMonthQualityReport previousReport = postcheckDao.getMonthQualityReport(previous[0], previous[1]);
		PostcheckMonthSanweiReport currentSanweiReport = postcheckDao.getCorpMonthSanweiReport(year, month);
		boolean isNewSeason = month % 3 == 1;
		for (Long chushiID : chushiList.keySet()) {
			// For each chushi
			ChushiReport previousChushiReport = previousReport == null ? null : previousReport.getChushiReportMap().get(chushiID);
			ChushiReport currentChushiReport = report.getChushiReportMap().get(chushiID);
			if (currentChushiReport == null) {
				currentChushiReport = report.new ChushiReport();
			}
			report.getChushiReportMap().put(chushiID, currentChushiReport);

			// set employee count
			Integer employeeCount = previousChushiReport == null ? null : previousChushiReport.getEmployeeCount();
			currentChushiReport.setEmployeeCount(employeeCount);

			// set worker count
			Integer workerCount = previousChushiReport == null ? null : previousChushiReport.getWorkerCount();
			currentChushiReport.setWorkerCount(workerCount);

			// set check unit count need
			Integer[] checkUnitCountNeed = previousChushiReport == null ? new Integer[3] : previousChushiReport.getCheckUnitCountNeed();
			if (isNewSeason) {
				Integer[] tmp = new Integer[3];
				tmp[0] = checkUnitCountNeed[2];
				checkUnitCountNeed = tmp;
			} else if (monthIndex > 0) {
				checkUnitCountNeed[monthIndex] = checkUnitCountNeed[monthIndex - 1];
			}
			currentChushiReport.setCheckUnitCountNeed(checkUnitCountNeed);

			if (isNewSeason) {
				previousChushiReport = null;
			}

			// set check unit count real
			Integer[] checkUnitCountReal = previousChushiReport == null ? new Integer[3] : previousChushiReport.getCheckUnitCountReal();
			currentChushiReport.setCheckUnitCountReal(checkUnitCountReal);

			// set mantime real
			Integer[] mantimeReal = previousChushiReport == null ? new Integer[3] : previousChushiReport.getMantimeReal();
			mantimeReal[monthIndex] = postcheckDao.getChushiMantime(year, month, 1, currentMonthEnd, chushiID);
			currentChushiReport.setMantimeReal(mantimeReal);

			// set problem count
			Integer[] problemCount = previousChushiReport == null ? new Integer[3] : previousChushiReport.getProblemCount();
			problemCount[monthIndex] = chushiProblemCountMap.get(chushiID);
			currentChushiReport.setProblemCount(problemCount);

			// set grade sum
			Integer[] gradeSum = previousChushiReport == null ? new Integer[3] : previousChushiReport.getGradeSum();
			gradeSum[monthIndex] = chushiGradeSumMap.get(chushiID);
			currentChushiReport.setGradeSum(gradeSum);

			// set isSanwei count
			Integer[] isSanweiCount = previousChushiReport == null ? new Integer[3] : previousChushiReport.getIsSanweiCount();
			isSanweiCount[monthIndex] = currentSanweiReport != null && currentSanweiReport.getChushiTable() != null ? currentSanweiReport
					.getChushiTable().get(chushiID) : null;
			currentChushiReport.setIsSanweiCount(isSanweiCount);

			// set finish rate
			Integer[] finishRate = previousChushiReport == null ? new Integer[] { 0, 0, 0, 0 } : previousChushiReport.getFinishRate();
			// calculate current finish rate
			if (checkUnitCountNeed[monthIndex] != null && checkUnitCountReal[monthIndex] != null) {
				finishRate[monthIndex] = (int) (checkUnitCountReal[monthIndex] / (checkUnitCountNeed[monthIndex] * 1.0) * 30 * 100);
				finishRate[monthIndex] = finishRate[monthIndex] > 30 * 100 ? 30 * 100 : finishRate[monthIndex];
			} else {
				finishRate[monthIndex] = 0;
			}
			calAverage(finishRate);
			currentChushiReport.setFinishRate(finishRate);

			// set partake rate
			Integer[] partakeRate = previousChushiReport == null ? new Integer[] { 0, 0, 0, 0 } : previousChushiReport.getPartakeRate();
			if (mantimeReal[monthIndex] != null && workerCount != null) {
				partakeRate[monthIndex] = (int) (mantimeReal[monthIndex] / (workerCount * 1.0) * 20 * 100);
				partakeRate[monthIndex] = partakeRate[monthIndex] > 20 * 100 ? 20 * 100 : partakeRate[monthIndex];
			} else {
				partakeRate[monthIndex] = 0;
			}
			calAverage(partakeRate);
			currentChushiReport.setPartakeRate(partakeRate);

			// set coverage rate
			Integer[] coverageRate = previousChushiReport == null ? new Integer[] { 0, 0, 0, 0 } : previousChushiReport.getCoverageRate();
			if (problemCount[monthIndex] != null && workerCount != null) {
				coverageRate[monthIndex] = (int) (problemCount[monthIndex] / (workerCount * 1.0) * 40 * 100);
				coverageRate[monthIndex] = coverageRate[monthIndex] > 40 * 100 ? 40 * 100 : coverageRate[monthIndex];
			} else {
				coverageRate[monthIndex] = 0;
			}
			calAverage(coverageRate);
			currentChushiReport.setCoverageRate(coverageRate);

			// set sanwei rate
			Integer[] sanweiRate = previousChushiReport == null ? new Integer[] { 0, 0, 0, 0 } : previousChushiReport.getCoverageRate();
			if (isSanweiCount[monthIndex] != null) {
				sanweiRate[monthIndex] = isSanweiCount[monthIndex] * 10 * 100;
			} else {
				sanweiRate[monthIndex] = 0;
			}
			calAverage(sanweiRate);
			currentChushiReport.setSanweiRate(sanweiRate);

			// set assess rate
			Integer[] assessRate = previousChushiReport == null ? new Integer[] { 0, 0, 0, 0 } : previousChushiReport.getAssessRate();
			assessRate[monthIndex] = finishRate[monthIndex] + partakeRate[monthIndex] + coverageRate[monthIndex] + sanweiRate[monthIndex];
			calAverage(assessRate);
			currentChushiReport.setAssessRate(assessRate);
		}
	}

	private void calAverage(Integer[] nums) {
		nums[3] = (nums[0] + nums[1] + nums[2]) / 3;
	}

	public PostcheckMonthQualityReport createQualityReport(int year, int month) {
		PostcheckMonthQualityReport report = new PostcheckMonthQualityReport(year, month);

		DepartmentDao departDao = DaoCreator.createDepartmentDao();
		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();

		// init shiyebu list
		Map<Long, Department1> shiyebuList = report.getShiyebuList();
		Long[] depart1IDs = new Long[] { Constants.SHIYEBU_ID_LIANYOU1, Constants.SHIYEBU_ID_LIANYOU2, Constants.SHIYEBU_ID_LIANYOU3,
				Constants.SHIYEBU_ID_LIANYOU4, Constants.SHIYEBU_ID_LIANYOU5, Constants.SHIYEBU_ID_HUAGONG1, Constants.SHIYEBU_ID_HUAGONG2,
				Constants.SHIYEBU_ID_HUAGONG3, Constants.SHIYEBU_ID_HUAGONG4, Constants.SHIYEBU_ID_CHUYUN1, Constants.SHIYEBU_ID_CHUYUN2,
				Constants.SHIYEBU_ID_DONGLIGUANLI, Constants.SHIYEBU_ID_SHUIWUGUANLI, Constants.SHIYEBU_ID_CHANPINFENXIFUWU };
		for (Long depart1ID : depart1IDs) {
			Department1 depart1 = departDao.getDepartment1ByID(depart1ID);
			shiyebuList.put(depart1.getId(), depart1);
		}

		// init chushi list
		Map<Long, Department1> chushiList = report.getChushiList();
		for (Long chushiID : Constants.CHUSHI_IDS_POSTCHECKREPORT) {
			chushiList.put(chushiID, departDao.getDepartment1ByID(chushiID));
		}

		// init postcheck list
		Map<Long, PostCheck> postcheckList = report.getPostcheckList();
		for (PostCheck postcheck : postcheckDao.getPostCheckByIDArray(Constants.POSTCHECK_IDS_QUALITYREPORT)) {
			postcheckList.put(postcheck.getId(), postcheck);
		}

		createShiyebuQualityReport(report, year, month);
		createChushiQualityReport(report, year, month);

		return report;
	}

	private boolean refreshMonthQualityReport(HttpServletRequest request, PostcheckMonthQualityReport report) {
		String paramJSON = request.getParameter(Constants.REQUEST_PARAMETER_PARAM_JSON);
		JSONObject jsonObj = null;
		try {
			jsonObj = new JSONObject(paramJSON);

			Long depart1ID = null;
			if (JSONObject.getNames(jsonObj) == null) {
				return true;
			}
			for (String key : JSONObject.getNames(jsonObj)) {
				String value = jsonObj.getString(key);

				try {
					if (key.indexOf("workerCount") >= 0) {
						depart1ID = Util.extractEntityID(key, "workerCount");
						report.setShiyebuWorkerCount(depart1ID, Integer.parseInt(value));
					} else if (key.indexOf("unitCount") >= 0) {
						depart1ID = Util.extractEntityID(key, "unitCount");
						report.setUnitCount(depart1ID, Integer.parseInt(value));
					} else if (key.indexOf("employeeCount") >= 0) {
						depart1ID = Util.extractEntityID(key, "employeeCount");
						report.setEmployeeCount(depart1ID, Integer.parseInt(value));
					} else if (key.indexOf("chushiWorkerCount") >= 0) {
						depart1ID = Util.extractEntityID(key, "chushiWorkerCount");
						report.setChushiWorkerCount(depart1ID, Integer.parseInt(value));
					} else if (key.indexOf("chushiCheckUnitCountNeed") >= 0) {
						depart1ID = Util.extractEntityID(key, "chushiCheckUnitCountNeed");
						report.setChushiCheckUnitCountNeed(depart1ID, Integer.parseInt(value));
					} else if (key.indexOf("chushiCheckUnitCountReal") >= 0) {
						depart1ID = Util.extractEntityID(key, "chushiCheckUnitCountReal");
						report.setChushiCheckUnitCountReal(depart1ID, Integer.parseInt(value));
					}
				} catch (Exception e) {
					continue;
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	private void refreshShiyebuQualityReport(PostcheckMonthQualityReport report, Long depart1ID) {
		// handle shiyebu report
		ShiyebuReport shiyebuReport = report.getShiyebuReportMap().get(depart1ID);
		if (shiyebuReport == null) {
			return;
		}

		/**
		 * params depend on worker count
		 */
		Integer workerCount = shiyebuReport.getWorkerCount();
		Integer dailyPartakeRate = null;
		if (workerCount != null) {
			// Calculate mantime need
			Integer mantimeNeed = report.getWorkingDay() * workerCount;
			shiyebuReport.setMantimeNeed(mantimeNeed);
			// Daily partake rate
			dailyPartakeRate = (int) (shiyebuReport.getMantimeReal() / (mantimeNeed * 1.0) * 10 * 100);
			dailyPartakeRate = dailyPartakeRate > 10 * 100 ? 10 * 100 : dailyPartakeRate;
			shiyebuReport.setDailyPartakeRate(dailyPartakeRate);
		}

		/**
		 * params depend on unit count
		 */
		Integer unitCount = shiyebuReport.getUnitCount();
		Integer dailyFinishRate = null;
		if (unitCount != null) {
			// Calculate check unit count
			Integer checkUnitCountNeed = report.getWorkingDay() * unitCount * 5;
			shiyebuReport.setCheckUnitCountNeed(checkUnitCountNeed);
			// Daily plan finish rate
			dailyFinishRate = (int) (shiyebuReport.getCheckUnitCountReal() / (checkUnitCountNeed * 1.0) * 10 * 100);
			if (dailyFinishRate > 10 * 100) {
				dailyFinishRate = 10 * 100;
			}
			shiyebuReport.setDailyFinishRate(dailyFinishRate);
		}

		if (dailyFinishRate != null && dailyPartakeRate != null) {
			Integer assessGrade = dailyFinishRate + dailyPartakeRate + shiyebuReport.getClosedRate() + shiyebuReport.getSlefCheckRate()
					+ shiyebuReport.getSanwei();
			for (Integer bigPostcheckRate : shiyebuReport.getCoverageMap().values()) {
				assessGrade += bigPostcheckRate;
			}
			shiyebuReport.setAssessGrade(assessGrade);
		}

	}

	private void refreshChushiQualityReport(PostcheckMonthQualityReport report, Long depart1ID) {
		ChushiReport chushiReport = report.getChushiReportMap().get(depart1ID);
		if (chushiReport == null) {
			return;
		}

		int monthIndex = Util.getMonthIndexInSeason(report.getMonth());

		Integer assessRate = 0;
		Integer workerCount = chushiReport.getWorkerCount();
		Integer checkUnitCountNeed = chushiReport.getCheckUnitCountNeed()[monthIndex];
		Integer checkUnitCountReal = chushiReport.getCheckUnitCountReal()[monthIndex];
		Integer mantimeReal = chushiReport.getMantimeReal()[monthIndex];
		Integer problemCount = chushiReport.getProblemCount()[monthIndex];

		// finish rate
		Integer finishRate = null;
		if (checkUnitCountNeed != null && checkUnitCountReal != null) {
			finishRate = (int) (checkUnitCountReal / (checkUnitCountNeed * 1.0) * 30 * 100);
			finishRate = finishRate > 30 * 100 ? 30 * 100 : finishRate;
		}
		if (finishRate != null) {
			Integer[] finishRates = chushiReport.getFinishRate();
			finishRates[monthIndex] = finishRate;
			calAverage(finishRates);
			chushiReport.setFinishRate(finishRates);

			assessRate += finishRate;
		}

		// partake rate
		Integer partakeRate = null;
		if (mantimeReal != null && workerCount != null) {
			partakeRate = (int) (mantimeReal / (workerCount * 1.0) * 20 * 100);
			partakeRate = partakeRate > 20 * 100 ? 20 * 100 : partakeRate;
		}
		if (partakeRate != null) {
			Integer[] partakeRates = chushiReport.getPartakeRate();
			partakeRates[monthIndex] = partakeRate;
			calAverage(partakeRates);
			chushiReport.setPartakeRate(partakeRates);

			assessRate += partakeRate;
		}

		// coverage rate
		Integer coverageRate = null;
		if (problemCount != null && workerCount != null) {
			coverageRate = (int) (problemCount / (workerCount * 1.0) * 40 * 100);
			coverageRate = coverageRate > 40 * 100 ? 40 * 100 : coverageRate;
		}
		if (coverageRate != null) {
			Integer[] coverageRates = chushiReport.getCoverageRate();
			coverageRates[monthIndex] = coverageRate;
			calAverage(coverageRates);
			chushiReport.setCoverageRate(coverageRates);

			assessRate += coverageRate;
		}

		assessRate += chushiReport.getSanweiRate()[monthIndex];
		Integer[] assessRates = chushiReport.getAssessRate();
		assessRates[monthIndex] = assessRate;
		calAverage(assessRates);
		chushiReport.setAssessRate(assessRates);

	}

	private boolean refreshMonthQualityReport(PostcheckMonthQualityReport report) {
		for (Long depart1ID : report.getShiyebuList().keySet()) {
			refreshShiyebuQualityReport(report, depart1ID);
		}
		for (Long depart1ID : report.getChushiList().keySet()) {
			refreshChushiQualityReport(report, depart1ID);
		}
		return true;
	}

	public boolean writeMonthQualityReport(HttpServletRequest request) {
		HttpSession session = request.getSession();
		User user = (User) session.getAttribute(Constants.SESSION_USER);

		PostcheckMonthQualityReport report = (PostcheckMonthQualityReport) session
				.getAttribute(Constants.SESSION_POSTCHECK_MONTH_QUALITY_REPORT);
		if (report == null) {
			return false;
		}

		refreshMonthQualityReport(request, report);
		refreshMonthQualityReport(report);

		Calendar cal = Calendar.getInstance();
		report.setShiyebuWriteUserID(user.getId());
		report.setShiyebuWriteUserName(user.getName());
		report.setShiyebuWriteTime(cal);
		report.setChushiWriteUserID(user.getId());
		report.setChushiWriteUserName(user.getName());
		report.setChushiWriteTime(cal);

		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();

		boolean isSuccess = postcheckDao.updateMonthQualityReport(report);
		session.removeAttribute(Constants.SESSION_POSTCHECK_MONTH_QUALITY_REPORT);

		return isSuccess;
	}

	public boolean generateMonthQualityReport(HttpServletRequest request) {
		HttpSession session = request.getSession();
		User user = (User) session.getAttribute(Constants.SESSION_USER);

		Integer year = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_YEAR, 0);
		Integer month = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_MONTH, 0);

		PostcheckMonthQualityReport report = createQualityReport(year, month);

		Calendar cal = Calendar.getInstance();
		report.setShiyebuWriteUserID(user.getId());
		report.setShiyebuWriteUserName(user.getName());
		report.setShiyebuWriteTime(cal);
		report.setChushiWriteUserID(user.getId());
		report.setChushiWriteUserName(user.getName());
		report.setChushiWriteTime(cal);

		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();
		postcheckDao.addMonthQualityReport(null, report);

		request.setAttribute(Constants.REQUEST_ATTRIBUTE_POSTCHECK_MONTH_QUALITY_REPORT, report);

		return true;
	}

	public boolean writeDepartMonthSanweiReport(HttpServletRequest request) {
		HttpSession session = request.getSession();
		UserAction userAction = ActionCreator.createUserAction();
		RoleDao roleDao = DaoCreator.createRoleDao();
		Role userRole = userAction.getUserRole(request);
		int processMethod = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_PROCESS_METHOD, 0);
		if (!roleDao.hasRight(Constants.AUTH_TYPE_POSTCHECK_MONTH_SANWEI_REPORT, userRole.getId(), processMethod)) {
			switch (processMethod) {
			case Constants.PROCESS_METHOD_CLOSE:
				request.setAttribute(Constants.REQUEST_ATTRIBUTE_ERROR, Constants.ERROR_KEY_IS_NOT_AUTHORIZED_CLOSE);
				break;
			case Constants.PROCESS_METHOD_ESCALATE:
				request.setAttribute(Constants.REQUEST_ATTRIBUTE_ERROR, Constants.ERROR_KEY_IS_NOT_AUTHORIZED_SANWEI_ESCALATE);
				break;
			}
			return false;
		}

		PostcheckMonthSanweiReport report = (PostcheckMonthSanweiReport) session
				.getAttribute(Constants.SESSION_POSTCHECK_DEPART_MONTH_SANWEI_REPORT);
		if (report == null) {
			return false;
		}
		if (!refreshMonthSanweiReport(request, report)) {
			return false;
		}

		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();

		boolean isSuccess = this.createNewProblem(request, report.getDepart1ID(), Constants.PROBLEM_TYPE_POSTCHECK_MONTH_SANWEI_REPORT);
		Problem newProblem = (Problem) request.getAttribute(Constants.REQUEST_ATTRIBUTE_NEW_PROBLEM);
		request.removeAttribute(Constants.REQUEST_ATTRIBUTE_NEW_PROBLEM);
		if (!isSuccess) {
			return false;
		}

		report.setProblemID(newProblem.getId());
		isSuccess = postcheckDao.addMonthSanweiReport(newProblem.getId(), report);

		session.removeAttribute(Constants.SESSION_POSTCHECK_DEPART_MONTH_CHECK_REPORT);

		if (processMethod == Constants.PROCESS_METHOD_CLOSE) {
			isSuccess = writeCorpSanweiReport(request, report);
			if (!isSuccess) {
				return false;
			}
		}
		return true;
	}

	public boolean writeDepartMonthCheckSummaryReport(HttpServletRequest request) {
		HttpSession session = request.getSession();

		UserAction userAction = ActionCreator.createUserAction();
		RoleDao roleDao = DaoCreator.createRoleDao();
		Role userRole = userAction.getUserRole(request);
		int processMethod = RequestUtil.getParameter(request, Constants.REQUEST_PARAMETER_PROCESS_METHOD, 0);
		if (!roleDao.hasRight(Constants.AUTH_TYPE_POSTCHECK_MONTH_CHECK_REPORT, userRole.getId(), processMethod)) {
			switch (processMethod) {
			case Constants.PROCESS_METHOD_CLOSE:
				request.setAttribute(Constants.REQUEST_ATTRIBUTE_ERROR, Constants.ERROR_KEY_IS_NOT_AUTHORIZED_CLOSE);
				break;
			case Constants.PROCESS_METHOD_ESCALATE:
				request.setAttribute(Constants.REQUEST_ATTRIBUTE_ERROR, Constants.ERROR_KEY_IS_NOT_AUTHORIZED_ESCALATE);
				break;
			}
			return false;
		}

		PostcheckDepartMonthCheckSummaryReport report = (PostcheckDepartMonthCheckSummaryReport) session
				.getAttribute(Constants.SESSION_POSTCHECK_DEPART_MONTH_CHECK_REPORT);
		if (report == null) {
			return false;
		}

		if (!refreshMonthCheckReport(request, report)) {
			return false;
		}

		PostCheckDao postcheckDao = DaoCreator.createPostCheckDao();

		boolean isSuccess = createNewProblem(request, report.getDepart1ID(), Constants.PROBLEM_TYPE_POSTCHECK_MONTH_CHECK_REPORT);
		Problem newProblem = (Problem) request.getAttribute(Constants.REQUEST_ATTRIBUTE_NEW_PROBLEM);
		request.removeAttribute(Constants.REQUEST_ATTRIBUTE_NEW_PROBLEM);
		if (!isSuccess) {
			return false;
		}

		isSuccess = postcheckDao.addMonthCheckSummaryReport(newProblem.getId(), report);

		session.removeAttribute(Constants.SESSION_POSTCHECK_DEPART_MONTH_CHECK_REPORT);
		return true;
	}

}
